package com.lqjava.flowable.beans.utils;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.lqjava.flowable.beans.convertor.common.CommonConvertor;
import lombok.Getter;
import org.springframework.beans.BeanUtils;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class MyBatisSQLInfo<T> {

    private static final Set<String> notTextColSimpClassNameSet = new HashSet() {{
        add("Integer");
        add("Long");
        add("BigDecimal");
        add("Boolean");
    }};


    public MyBatisSQLInfo(Class<T> clazz){
        this.clazz = clazz;
        this.init();
    }
    private Class<T> clazz;
    @Getter
    private String tableName;
    private String idColName;
    private List<String> colList = new ArrayList<>();
    private List<Field> fieldList = new ArrayList<>();

    private void init(){
        TableName tableNameAnnotation= this.clazz.getAnnotation(TableName.class);
        this.tableName = tableNameAnnotation != null && StrUtil.isNotBlank(tableNameAnnotation.value()) ? tableNameAnnotation.value() : StrUtil.toUnderlineCase(this.clazz.getSimpleName());
        Field[] declaredFields = this.clazz.getDeclaredFields();
        for (int i = 0; i < declaredFields.length; i++) {
            Field field = declaredFields[i];
            TableField tableFiled = field.getAnnotation(TableField.class);
            String fieldName = field.getName();
            String colName = tableFiled != null && StrUtil.isNotBlank(tableFiled.value()) ? tableFiled.value() :  StrUtil.toUnderlineCase(fieldName);
            if(field.getAnnotation(TableId.class) != null) this.idColName = colName;
            this.colList.add(colName);
            this.fieldList.add(field);
        }
    }
    public String getInsertCols(){
        StringBuffer sb = new StringBuffer();
        this.colList.forEach(col -> {
            sb.append("`").append(col).append("`").append(",");
        });
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }
    public String getInsertValues(T entity){
        StringBuffer sb = new StringBuffer();
        int size = this.fieldList.size();
        for (int i = 0; i < size; i++) {
            Field field = this.fieldList.get(i);
            String simpleName = field.getType().getSimpleName();
            Object value = getFieldValue(field, entity);
            boolean notText= notTextColSimpClassNameSet.contains(simpleName);
            if(value != null && !notText) sb.append("'");
            sb.append(value);
            if(value != null && !notText) sb.append("'");
            sb.append(",");
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }

    public String getUpdateSet(T entity){
        StringBuffer sb = new StringBuffer();
        int size = this.fieldList.size();
        for (int i = 0; i < size; i++) {
            String col = this.colList.get(i);
            if(col.equals(this.idColName)) continue;

            Field field = this.fieldList.get(i);
            String simpleName = field.getType().getSimpleName();
            Object value = getFieldValue(field, entity);
            if(value == null) continue;

            boolean notText= notTextColSimpClassNameSet.contains(simpleName);
            sb.append(col).append(" = ");
            if(value != null && !notText) sb.append("'");
            sb.append(value);
            if(value != null && !notText) sb.append("'");
            sb.append(",");
        }
        sb.deleteCharAt(sb.length() - 1);
        return sb.toString();
    }


    private Object getFieldValue(Field field,T entity){
        String simpleName = field.getType().getSimpleName();
        PropertyDescriptor pd = BeanUtils.getPropertyDescriptor(clazz, field.getName());
        if(pd == null) return null;
        Method method = pd.getReadMethod();
        if(method == null)  return null;
        Object value = null;
        try {
            value = method.invoke(entity);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if(value == null) return  null;
        if("LocalTime".equals(simpleName)){
            value = LocalDateTimeUtils.format((LocalTime)value);
        }else if("LocalDate".equals(simpleName)){
            value = LocalDateTimeUtils.format((LocalDate)value);
        }else if("LocalDateTime".equals(simpleName)) {
            value = LocalDateTimeUtils.format((LocalDateTime)value);
        }
        return value;
    }



}
